package com.pc.ipushpin.common.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.pc.ipushpin.common.manager.MyX509TrustManager;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Base64Utils;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.*;
import java.security.spec.InvalidParameterSpecException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * 
 * 请求数据通用类
 * @author Bo
 *
 */


public class WechatUtil {

	//日志记录器
	private static final Logger log= LoggerFactory.getLogger(WechatUtil.class);
	// token
//		public static String token = "WeiXinEnterprises";
		// 随机戳
		public static String encodingAESKey = "4hX8uoE1AcJLkKIplveNgZy5kUGfCgVbqOChiZ7cxwS";
		// 你的企业号ID
		
//		public static String appId = "wx4ff8993bde1d9a37";
//		public static String appSecret = "7a9d86fb50520b97c01039790b0271a9";
		
//		public static String appId = "wxad9c2989adfc6618";
//		public static String appSecret = "6d626e8e0bd434e6b7fb43494d0f2278";
		
		public static String appId = StwConstant.WECHAT_GZ_APP_ID;
		public static String appSecret = StwConstant.WECHAT_GZ_APP_KEY;
		
		
		//网页js网页ticket
		public static String jsapi_ticket = "";
		public static String REDIRECT_URI = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_userinfo&state=STATE&connect_redirect=1#wechat_redirect";
		//域名
//		public static String HOST_URI = "http://hi.icoderlab.com/";
		//微信菜单入口

		public final static String jsapi_ticket_url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
		// 获取access_token的接口地址（GET）
		public final static String access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
		// 获取用户授权token
		public static String wx_ticket_create_url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
		// 获取用户信息
		public static String wx_user_token_url = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
	/**
	 * 发起https请求并获取结果
	 * 
	 * @param requestUrl
	 *            请求地址
	 * @param requestMethod
	 *            请求方式（GET、POST）
	 * @param outputStr
	 *            提交的数据
	 * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
	 */
	public static JSONObject httpRequest(String request, String RequestMethod, String output) {
		JSONObject jsonObject = null;
		StringBuffer buffer = new StringBuffer();
		try {
			
			// 建立连接
			URL url = new URL(request);
			HttpURLConnection connection = (HttpURLConnection) url.openConnection();
			connection.setDoOutput(true);
			connection.setDoInput(true);
			connection.setUseCaches(false);
			connection.setRequestMethod(RequestMethod);
			if (output != null) {
				OutputStream out = connection.getOutputStream();
				out.write(output.getBytes("UTF-8"));
				out.close(); 
			}
			// 流处理
			InputStream input = connection.getInputStream();
			InputStreamReader inputReader = new InputStreamReader(input, "UTF-8");
			BufferedReader reader = new BufferedReader(inputReader);
			String line;
			while ((line = reader.readLine()) != null) {
				buffer.append(line);
			}
			// 关闭连接、释放资源
			reader.close();
			inputReader.close();
			input.close();
			input = null;
			connection.disconnect();
			jsonObject = JSONObject.parseObject(buffer.toString());
		} catch (Exception e) {
		}
		return jsonObject;
	}


	/**
	 * 获取access_token
	 * 
	 * @param appId
	 *            企业Id
	 * @param SECRET
	 *            管理组的凭证密钥，每个secret代表了对应用、通讯录、接口的不同权限；不同的管理组拥有不同的secret
	 * @return
	 */
		
	public static String getAccessToken() {
		String accessToken ="";
		try {
			String requestUrl = access_token_url.replace("APPID", appId).replace("APPSECRET", appSecret);
			JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
			if (null != jsonObject && jsonObject.containsKey("access_token")) {
				accessToken =  jsonObject.getString("access_token");
				System.out.println("获取token成功:" + jsonObject.getString("access_token") + "————" + jsonObject.getInteger("expires_in"));
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return accessToken;
	}
	
    public static JSONObject httpsRequest1(String requestUrl,String requestMethod,String outputStr){  
    	JSONObject jsonObject = null;
    	StringBuffer buffer=null;  
        try{  
	        //创建SSLContext  
	        SSLContext sslContext=SSLContext.getInstance("SSL");  
	        TrustManager[] tm={new MyX509TrustManager()};
	        //初始化  
	        sslContext.init(null, tm, new java.security.SecureRandom());;  
	        //获取SSLSocketFactory对象  
	        SSLSocketFactory ssf=sslContext.getSocketFactory();  
	        URL url=new URL(requestUrl);  
	        HttpsURLConnection conn=(HttpsURLConnection)url.openConnection();  
	        conn.setDoOutput(true);  
	        conn.setDoInput(true);  
	        conn.setUseCaches(false);  
	        conn.setRequestMethod(requestMethod);  
	        //设置当前实例使用的SSLSoctetFactory  
	        conn.setSSLSocketFactory(ssf);  
	        conn.connect();  
	        //往服务器端写内容  
	        if(null!=outputStr){  
	            OutputStream os=conn.getOutputStream();  
	            os.write(outputStr.getBytes("utf-8"));  
	            os.close();  
	        }  
	          
	        //读取服务器端返回的内容  
	        InputStream is=conn.getInputStream();  
	        InputStreamReader isr=new InputStreamReader(is,"utf-8");  
	        BufferedReader br=new BufferedReader(isr);  
	        buffer=new StringBuffer();   
	        String line=null;     
	        while((line=br.readLine())!=null){  
	            buffer.append(line);  
	        }  
	        jsonObject = JSONObject.parseObject(buffer.toString());
        }catch(Exception e){  
            e.printStackTrace();  
        }  
        return jsonObject;
    }  

	/**
	 * 
	 * 
	 * @param menu 获取用户授权token
	 */
	public static JSONObject getUserAccessToken(String AppID ,String secret, String code) {

		String wx_user_token_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
		// 拼装创建菜单的url
		String url = wx_user_token_url.replace("SECRET", secret).replace("APPID", AppID).replace("CODE", code);
		// 调用接口创建菜单
		JSONObject jsonObject = httpsRequest1(url, "GET", null);
		return jsonObject;
	}
	
	/**
	 * 
	 * 
	 * @param menu 获取用户信息
	 */
	public static JSONObject getUserInfo(String accessToken ,String openId) {

		// 拼装创建菜单的url
		String url = wx_user_token_url.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId);
		// 调用接口创建菜单
		JSONObject jsonObject = httpRequest(url, "GET", null);
		return jsonObject;
	}
	
	//微信授权公用方法
	public static Map<String,Object> authorizeUser(HttpServletRequest request) {
		Map<String,Object> result = new HashMap<String, Object>();
		//1 第一步：用户同意授权，获取code
		// 微信授权code
	     String code = request.getParameter("code"); 
	     result.put("authorizeCode", code);
//	     String state = request.getParameter("state");  
//	     System.out.println("authorizeUser:::state!!!!"+state);
	    //2 第二步：通过code换取网页授权access_token { "access_token":"ACCESS_TOKEN",  "expires_in":7200, "refresh_token":"REFRESH_TOKEN", "openid":"OPENID","scope":"SCOPE", "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"}
	    if(code == null || "authdeny".equals(code)){
	    	result.put("msg", "无法获取code");
	    	result.put("success", false);
		} else {
			JSONObject tokenJo = WechatUtil.getUserAccessToken(appId, appSecret, code);
			// 保存
			result.put("getUserAccessToken", tokenJo);
			// 获取用户信息
			if (tokenJo != null) {
				if (tokenJo.toString().contains("access_token")) {
					JSONObject userInfoJo = WechatUtil.getUserInfo(tokenJo.getString("access_token"),
							tokenJo.getString("openid"));
					result.put("data", userInfoJo);
					result.put("msg", "成功获取");
					result.put("success", true);
				} else {
					result.put("msg", "无法获取token");
					result.put("success", false);
				}

			} else {
				result.put("msg", "无法获取token");
				result.put("success", false);
			}
		}
		return result;
	}
	/**
	 * 
	 * 
	 * @param menu
	 *            获取 Ticket
	 * @param accessToken
	 *            有效的access_token
	 * @param agentid
	 *            企业应用的id，整型，可在应用的设置页面查看
	 * @return 0表示成功，其他值表示失败
	 */
	public static JSONObject createWxJsTicket(String accessToken) {

		// 拼装创建菜单的url
		String url = wx_ticket_create_url.replace("ACCESS_TOKEN", accessToken);
		// 调用接口创建菜单
		JSONObject jsonObject = httpRequest(url, "GET", null);
		return jsonObject;
	}
	



	/**
	 * 获取sign
	 * @return
	 */
	public static String getSign(String url, String timestamp, String nonceStr, String jsapi_ticket) {

		System.err.println("url"+url+"timestamp"+timestamp+"nonceStr"+ nonceStr+"jsapi_ticket"+jsapi_ticket );
	     String[] str = { url, timestamp, nonceStr, jsapi_ticket };  
	     Arrays.sort(str); // 字典序排序  
	     String bigStr = str[0] + str[1] + str[2]+ str[3];  
	     // SHA1加密  
	     System.out.println(bigStr);
	     String digest = new SHA1().getDigestOfString(bigStr.getBytes())  
	             .toLowerCase(); 
		return digest;
	}
	
	
	/**
	 * 获取sign
	 * @return
	 */
	public static String getJsSign(String url, String timestamp, String nonceStr, String jsapi_ticket) {

		System.err.println("url"+url+"timestamp"+timestamp+"nonceStr"+ nonceStr+"jsapi_ticket"+jsapi_ticket );
	    String  str ="jsapi_ticket="+jsapi_ticket+"&noncestr="+nonceStr+"&timestamp="+timestamp+"&url="+url;
	    System.out.println(str);
	     String digest = new SHA1().getDigestOfString(str.getBytes())  
	             .toLowerCase(); 
	     
		return digest;
	}
	
	/**
	 * https://mp.weixin.qq.com/debug/wxadoc/dev/api/api-login.html#wxloginobject
	 * //正常返回的JSON数据包
		{
		      "openid": "OPENID",
		      "session_key": "SESSIONKEY",
		      "unionid": "UNIONID"
		}
		//错误时返回JSON数据包(示例为Code无效)
		{
		    "errcode": 40029,
		    "errmsg": "invalid code"
		}
	 * 
	 * @param 小程序获取用户授权信息
	 */
	public static JSONObject getSessionKeyForUser(String jsCode) {
		// code 换取 session_key
		String wx_user_token_url = "https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code";
		String url = wx_user_token_url.replace("APPID", StwConstant.WECHAT_SP_APP_ID).replace("SECRET", StwConstant.WECHAT_SP_APP_KEY).replace("JSCODE", jsCode);
		JSONObject jsonObject = httpsRequest1(url, "GET", null);
		return jsonObject;
	}
	
	
	/*
	 * 微信jsd配置
	 * */
	public static Map<String,Object> getJsdConfig(String url,String token) {
		
		
		System.out.println("url" + url);
		Map<String,Object> data = new HashMap<String,Object>();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
		Timestamp now = new Timestamp(System.currentTimeMillis());//获取系统当前时间
		String timestamp = sdf.format(now);
		String noncestr ="wxjstoken";
		String weChatToken = getAccessToken();
		if(!"".equals(weChatToken)){
			String requestUrl = jsapi_ticket_url.replace("ACCESS_TOKEN", weChatToken);
			JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
			if(jsonObject.containsKey("errcode") && jsonObject.getInteger("errcode") == 0){
				String signature =WechatUtil.getJsSign(url, timestamp, noncestr, jsonObject.getString("ticket"));
				data.put("timestamp", timestamp);
				data.put("noncestr", noncestr);
				data.put("signature", signature);
				data.put("appId", appId);
			}
		}

		return data; 
	}

	public static  String getLoginUrl(){
		String url = StwConstant.CLOUDWEALTH_IMGSERVICE+"/wechat/userRegister";
		try {
			url = URLEncoder.encode(url, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return url;
	}
	
	public static Object getUserInfoByRedis(HttpServletRequest request, String key) {
		Object value = null;
		try {
//			Jedis jedis = RedisUtil.getJedisByPool();
//			//获取session id
//			HttpSession session = request.getSession();
//			String sessionId = session.getId();
//			String sessionKey = "api"+key+sessionId;
//			//获取redis
//			value = jedis.get(sessionKey);
//			if(jedis != null){
//				jedis.close();
//			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return value;	
	}
	public static void main(String[] args) throws Exception {
		
		SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");//定义格式，不显示毫秒
//		String wct = WechatUtil.getAccessToken();
		String url = "http://wx.woyes.com";
		
		System.err.println(getLoginUrl());

	}

	public static JSONObject getUserInfo(String encryptedData, String sessionKey, String iv) {
		// 被加密的数据
		byte[] dataByte = Base64Utils.decode(encryptedData.getBytes());
		// 加密秘钥
		byte[] keyByte = Base64Utils.decode(sessionKey.getBytes());
		// 偏移量
		byte[] ivByte = Base64Utils.decode(iv.getBytes());
		try {

			// 如果密钥不足16位，那么就补足.  这个if 中的内容很重要
			int base = 16;
			if (keyByte.length % base != 0) {
				int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
				byte[] temp = new byte[groups * base];
				Arrays.fill(temp, (byte) 0);
				System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
				keyByte = temp;
			}
			// 初始化
			Security.addProvider(new BouncyCastleProvider());
			Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
			SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
			AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
			parameters.init(new IvParameterSpec(ivByte));
			cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
			byte[] resultByte = cipher.doFinal(dataByte);
			if (null != resultByte && resultByte.length > 0) {
				String result = new String(resultByte, "UTF-8");
				return JSON.parseObject(result);
			}
		} catch (NoSuchAlgorithmException e) {
			log.error(e.getMessage(), e);
		} catch (NoSuchPaddingException e) {
			log.error(e.getMessage(), e);
		} catch (InvalidParameterSpecException e) {
			log.error(e.getMessage(), e);
		} catch (IllegalBlockSizeException e) {
			log.error(e.getMessage(), e);
		} catch (BadPaddingException e) {
			log.error(e.getMessage(), e);
		} catch (UnsupportedEncodingException e) {
			log.error(e.getMessage(), e);
		} catch (InvalidKeyException e) {
			log.error(e.getMessage(), e);
		} catch (InvalidAlgorithmParameterException e) {
			log.error(e.getMessage(), e);
		} catch (NoSuchProviderException e) {
			log.error(e.getMessage(), e);
		}
		return null;
	}


}
